package com.sjx.jnistudy

import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.SeekBar
import android.media.AudioAttributes
import android.os.SystemClock
import com.sjx.audiotest.ListBean
import com.sjx.audiotest.MockData
import com.sjx.jnistudy.swallow.SwallowAdapter
import com.sjx.jnistudy.swallow.SwallowViewHolder
import kotlinx.android.synthetic.main.activity_main2.*


class MainActivity2 : AppCompatActivity() {

    private val STREAM_TYPE = AudioManager.STREAM_MUSIC
    private val SAMPLE_RATE_IN_HZ = 8000 // 采样率
    private val CHANNEL_CONFIG = AudioFormat.CHANNEL_OUT_STEREO
    private val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
    private val MODE = AudioTrack.MODE_STREAM
    private val UPDATE_PRIODMS = 100

    private lateinit var list: ArrayList<ListBean>
    private lateinit var data: IntArray
    var sessionId: Int = 0
    private var playThread: MyPlayThread? = null
    private lateinit var waveData: ByteArray
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        list = MockData.getListDefalutData()
        val waveLen = SAMPLE_RATE_IN_HZ * 2 * UPDATE_PRIODMS / 1000
        waveData = ByteArray(waveLen)
        data = MockData.getMockFd()

//        initList()
        initList1()

//        baseWave = MockData.buildBaseWave(SAMPLE_RATE_IN_HZ * 2)
        baseWaveByte = MockData.buildBaseWaveByte(SAMPLE_RATE_IN_HZ * 2)


        val am = getSystemService(AUDIO_SERVICE) as AudioManager
        sessionId = am.generateAudioSessionId()

        playThread = MyPlayThread()
        playThread?.init()
        playThread?.start()

        btn_play.setOnClickListener {
            playThread?.isPlaying = true
        }

        btn_stop.setOnClickListener {
            playThread?.isPlaying = false
        }


        for (i in 0..29) {
            Log.e("TAG", "起始时间" + System.currentTimeMillis())
            val waveData = CalcUtils.sinWave(MockData.freq, data, SAMPLE_RATE_IN_HZ, 100, 100)
            Log.e("TAG", "终止时间" + System.currentTimeMillis())
            Log.e("TAG", waveData.size.toString() + "")
        }


    }

    override fun onDestroy() {
        super.onDestroy()
        playThread?.stopPlay()
    }

    private fun initList() {
        slv_hz.setAdapter(object : SwallowAdapter<ListBean>(R.layout.item_hz, list) {

            override fun onBind(position: Int, data: ListBean, holder: SwallowViewHolder) {
                val sb_hz = holder.getView<SeekBar>(R.id.sb_hz)
                sb_hz.progress = data.progress
                holder.setText(R.id.tv_hz_name, "${data.name}Hz")
                holder.setText(R.id.tv_hz_value, "${data.progress}")
                sb_hz.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                    override fun onProgressChanged(
                        seekBar: SeekBar,
                        progress: Int,
                        fromUser: Boolean
                    ) {
                        holder.setText(R.id.tv_hz_value, "$progress")
                        list[position].progress = progress
                    }

                    override fun onStartTrackingTouch(seekBar: SeekBar) {

                    }

                    override fun onStopTrackingTouch(seekBar: SeekBar) {

                    }
                })
            }
        })
    }

    private fun initList1() {
        slv_hz.setAdapter(object : SwallowAdapter<Int>(R.layout.item_hz, data.asList()) {

            override fun onBind(position: Int, progress: Int, holder: SwallowViewHolder) {
                val sb_hz = holder.getView<SeekBar>(R.id.sb_hz)
                sb_hz.progress = progress
                holder.setText(R.id.tv_hz_name, "${MockData.freq[position]}Hz")
                holder.setText(R.id.tv_hz_value, "${progress}")
                sb_hz.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                    override fun onProgressChanged(
                        seekBar: SeekBar,
                        progress: Int,
                        fromUser: Boolean
                    ) {
                        holder.setText(R.id.tv_hz_value, "$progress")
                        data[position] = progress
                        Log.e("TAG", "起始时间1：${System.currentTimeMillis()}")
                        CalcUtils.sinWave(MockData.freq, data, SAMPLE_RATE_IN_HZ * 2, UPDATE_PRIODMS, 100, waveData)
                        Log.e("TAG", "起始时间2：${System.currentTimeMillis()} -- ${waveData.size}")

                    }

                    override fun onStartTrackingTouch(seekBar: SeekBar) {

                    }

                    override fun onStopTrackingTouch(seekBar: SeekBar) {

                    }
                })
            }
        })
    }



    fun getBarProgress(): ArrayList<Int> {
//        val barProgress = ArrayList<Int>()
//        list.forEach {  }

        return list.map { it.progress } as ArrayList<Int>
    }

    inner class MyPlayThread : Thread() {
        var isPlaying = false
        private var mAudioTrack: AudioTrack? = null
        private var bufferSizeInBytes: Int = 0
        fun init() {
//            mAudioTrack = AudioTrack(
//                STREAM_TYPE, SAMPLE_RATE_IN_HZ,
//                CHANNEL_CONFIG, // CHANNEL_CONFIGURATION_MONO,
//                AUDIO_FORMAT,
//                SAMPLE_RATE_IN_HZ,
//                MODE
//            )
            bufferSizeInBytes = AudioTrack.getMinBufferSize(
                SAMPLE_RATE_IN_HZ,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT
            ) * 2
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO)

            mAudioTrack = AudioTrack(
                AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build(),
                AudioFormat.Builder()
                    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                    .setSampleRate(SAMPLE_RATE_IN_HZ)
                    .build(),
                bufferSizeInBytes,
                AudioTrack.MODE_STREAM,
                sessionId
            )
        }

        override fun run() {
            super.run()
            mAudioTrack?.play()
            //一直播放
            while (true) {
                if (isPlaying && baseWaveByte != null) {
//                    val waveData = MockData.getWaveDataFromBaseByte(
//                        getBarProgress(),
//                        sampleRate = SAMPLE_RATE_IN_HZ * 2
//                    )
                    // val waveData = MockData.getWaveData(list, SAMPLE_RATE_IN_HZ * 2 , 100)
//                    val waveData = MockData.getWaveDataFromBase(getBarProgress(),sampleRate = SAMPLE_RATE_IN_HZ * 2)
                    Log.e("TAG", "写入起始时间 -- ：${System.currentTimeMillis()}")
                    val i = mAudioTrack?.write(waveData, 0, waveData.size)
                    Log.e("TAG", "写入终止时间 -- ：${System.currentTimeMillis()}")
                    Log.e("TAG", "---------- 波形数据大小:${waveData.size}, 写入数量:${i}, 缓存Buffer大小:${bufferSizeInBytes} ----------")
                } else {
                    SystemClock.sleep(500)
                }
            }
        }

        fun stopPlay() {
            isPlaying = false
            releaseAudioTrack()
        }

        private fun releaseAudioTrack() {
            mAudioTrack?.stop()
            mAudioTrack?.release()
            mAudioTrack = null
        }
    }

    companion object {

        var baseWave: ArrayList<ArrayList<ArrayList<Double>>>? = null
        var baseWaveByte: ArrayList<ArrayList<ByteArray>>? = null
    }

}
